package org.example.tree;

import java.util.ArrayList;
import java.util.List;

/**
 * @ClassName  四叉树类，用于空间划分和快速查询
 * @Description TODO
 * @Author hongjun
 * @Date 2024/5/17 下午10:39
 * @Version 1.0
 */

class Quadtree {
    private Rectangle bounds; // 当前节点的边界
    private List<Block> blocks; // 存储在当前节点中的阻挡物
    private Quadtree[] nodes; // 子节点数组
    private int capacity; // 节点中最多可以存储的阻挡物数量
    private int level; // 四叉树的层级

    public Rectangle getBounds() {
        return bounds;
    }

    public void setBounds(Rectangle bounds) {
        this.bounds = bounds;
    }

    public List<Block> getBlocks() {
        return blocks;
    }

    public void setBlocks(List<Block> blocks) {
        this.blocks = blocks;
    }

    public Quadtree[] getNodes() {
        return nodes;
    }

    public void setNodes(Quadtree[] nodes) {
        this.nodes = nodes;
    }

    public int getCapacity() {
        return capacity;
    }

    public void setCapacity(int capacity) {
        this.capacity = capacity;
    }

    public int getLevel() {
        return level;
    }

    public void setLevel(int level) {
        this.level = level;
    }

    public Quadtree(Rectangle bounds, int level, int capacity) {
        this.bounds = bounds;
        this.level = level;
        this.capacity = capacity;
        this.blocks = new ArrayList<>();
        this.nodes = null;
    }

    // 将阻挡物添加到四叉树中
    public void addBlock(Block block) {
        if (!bounds.intersects(block.getBounds())) {
            return; // 阻挡物不在当前节点范围内，直接返回
        }

        if (nodes != null) {
            // 如果有子节点，尝试添加到子节点中
            for (Quadtree node : nodes) {
                node.addBlock(block);
            }
        } else {
            // 如果没有子节点，尝试添加到当前节点的阻挡物列表中
            if (blocks.size() < capacity) {
                blocks.add(block);
            } else {
                // 如果阻挡物列表已满，则分裂节点
                split();
                // 递归添加阻挡物到子节点中
                for (Quadtree node : nodes) {
                    node.addBlock(block);
                }
            }
        }
    }

    // 分裂节点，创建四个子节点
    private void split() {
        int subWidth = bounds.width / 2;
        int subHeight = bounds.height / 2;
        nodes = new Quadtree[4];
        nodes[0] = new Quadtree(new Rectangle(bounds.x, bounds.y, subWidth, subHeight), level + 1, capacity);
        nodes[1] = new Quadtree(new Rectangle(bounds.x + subWidth, bounds.y, subWidth, subHeight), level + 1, capacity);
        nodes[2] = new Quadtree(new Rectangle(bounds.x, bounds.y + subHeight, subWidth, subHeight), level + 1, capacity);
        nodes[3] = new Quadtree(new Rectangle(bounds.x + subWidth, bounds.y + subHeight, subWidth, subHeight), level + 1, capacity);
        // 将当前节点的阻挡物分配到子节点中
        for (Block block : blocks) {
            for (int i = 0; i < 4; i++) {
                nodes[i].addBlock(block);
            }
        }
        blocks.clear();
    }
    // 查询指定区域内的阻挡物
    public List<Block> queryRange(Rectangle range) {
        List<Block> blocksInRange = new ArrayList<>();
        if (!bounds.intersects(range)) {
            return blocksInRange; // 查询区域不在当前节点范围内，直接返回空列表
        }

        if (nodes != null) {
            // 如果有子节点，递归查询子节点中的阻挡物
            for (Quadtree node : nodes) {
                blocksInRange.addAll(node.queryRange(range));
            }
        }

        // 检查当前节点的阻挡物列表
        for (Block block : blocks) {
            if (range.intersects(block.getBounds())) {
                // 对于圆形阻挡物，可能需要进行精确碰撞检测
                if (block.getShape() == Block.Shape.CIRCLE && !block.getCircle().intersects(range)) {
                    continue; // 圆形与范围不相交，跳过
                }
                blocksInRange.add(block);
            }
        }
        return blocksInRange;
    }

    // 移动阻挡物到新的位置
    public void moveBlock(Block block, Rectangle newBounds) {
        removeBlock(block); // 先从树中移除原有的阻挡物
        block.setBounds(newBounds); // 更新阻挡物的边界
        addBlock(block); // 将阻挡物添加到新的位置
    }

    // 从四叉树中移除阻挡物
    public boolean removeBlock(Block block) {
        if (!bounds.intersects(block.getBounds())) {
            return false; // 阻挡物不在当前节点范围内，直接返回false
        }

        if (nodes != null) {
            // 如果有子节点，递归在子节点中移除阻挡物
            for (Quadtree node : nodes) {
                if (node.removeBlock(block)) {
                    return true; // 如果在子节点中成功移除，则返回true
                }
            }
        }

        // 如果没有子节点或子节点中没有找到阻挡物，尝试在当前节点的阻挡物列表中移除
        return blocks.remove(block);
    }

    // 检查给定的坐标(x, y)是否被任何阻挡物阻挡
    public boolean isBlocked(int x, int y) {
        // 检查坐标是否在当前节点的边界内
        if (!bounds.contains(x, y)) {
            return false; // 如果不在当前节点范围内，直接返回false
        }

        // 检查当前节点的阻挡物列表（如果有的话）
        if (blocks != null) {
            for (Block block : blocks) {
                if (block.getBounds().contains(x, y)) {
                    return true; // 如果坐标在某个阻挡物的边界内，返回true
                }
            }
        }

        // 如果有子节点，递归检查子节点
        if (nodes != null) {
            for (Quadtree node : nodes) {
                if (node.isBlocked(x, y)) {
                    return true; // 如果子节点返回true，表示找到了阻挡物，直接返回true
                }
            }
        }

        // 如果没有找到阻挡物，返回false
        return false;
    }


}
